/*
 * homedepotsingle.c
 *
 *  Created on: Jun 17, 2011
 *      Author: peckb1
 */

#include "syscall.h"
#include "usercommon.h"
#include "userSharedDefinitions.h"
#include "userItem.h"
#include "userAisle.h"

/* Data for everyone */
/* Locks* theLocksInHomeDepot; */
char *name;
int i;

UserItem itemsInStore[MAX_ITEMS];
int totalStoreSales;
int registerSales[MAX_CLERKS];

int _shelfLock[MAX_ITEMS]; /* Lock */
int _itemWaitCV[MAX_ITEMS]; /* Condition */
int _itemStockOnShelf[MAX_ITEMS];
int _customerWaitingForReStockLock; /* Lock */
int _stockBoyReStockingItem[MAX_ITEMS];
int _customersWaitingForRestock[MAX_ITEMS];

int _stockRoomStatusLock; /* Lock */
int _stockRoomLock; /* Lock */
int _stockBoyIdInStockRoom;
int _stockBoysWaitingForStockRoomCV;
int _stockRoomCV; /* Condition */
int _stockBoyOrderLock; /* Lock */

int _stockBoysStatusLock; /* Lock */
int _stockBoysStatus[MAX_STOCKBOYS]; /* which Aisle we're in */

int _stockBoyBreakLock; /* Lock */
int _stockBoysOnBreakCV; /* Condition */
int _stockBoyOnBreakMV; /* initial values set to zero */

int _clerksOnBreakLock; /* Lock */
int _clerksOnBreakCV; /* Condition */
int _clerksOnBreakMV; /* initial values set to zero */

int _signalManagerClerkHelp; /* Lock */
int _storeNeedsMoreClerks[MAX_CLERKS]; /* false if lines are ok, true if a clerk saw a line > 4 */

int _customerNeedsClerkAssitanceLock; /* Lock */
int _customerNeedsClerkAssitanceCV; /* Condition */
int _customerShouldFindTheClerkCV; /* Condition */
int _customersNeedingAsistanceMV; /* initial values set to zero */
int _clerkIDSignalingToCustomer;

int _registerNeedsMoney; /* Lock */
int _registerNeedsMoneyCV[MAX_CLERKS]; /* Condition */
int _moneyNeededForTill[MAX_CLERKS];
int _moneyGivenToTill[MAX_CLERKS];
int _registersThatNeedMoney;

int _customersWaitingInAisleToAskQuestionLock[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS]; /* Lock */
int _stockBoyIdInAisleToAnswerQuestionMV[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS];
int _customersWaitingInAisleToAskQuestionMV[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS];
int _customersWaitingInAisleToAskQuestionCV[NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS]; /* Condition */

int _customerItemQuestionLock[MAX_STOCKBOYS]; /* Lock */
int _customerItemQuestionMV[MAX_STOCKBOYS];
int _customerID_AskingQuestionMV[MAX_STOCKBOYS];
int _customerItemQuestionCV[MAX_STOCKBOYS]; /* Condition */

int _stockBoyAisleAnswerLock[MAX_STOCKBOYS]; /* Lock */
int _stockBoyAisleAnswerMV[MAX_STOCKBOYS];
int _stockBoyAisleAnswerCV[MAX_STOCKBOYS]; /* Condition */

int _clerkLinelock; /* Lock */
int _clerkLineCV[MAX_CLERKS]; /* CV for clerks */
int _clerkLineLength[MAX_CLERKS]; /* Line length for each clerk */
int _clerkStatus[MAX_CLERKS]; /* MV for clerks - 0 is at register, 1 is on break */

int _clerkLock[MAX_CLERKS]; /* Lock */
int _clerkCV[MAX_CLERKS]; /* Condition */
int _customerLock[MAX_CLERKS]; /* Lock */
int _customerCV[MAX_CLERKS]; /* Condition */
int _ItemPassingClerkLock[MAX_CLERKS]; /* Lock */
int _ItemPassingClerkCV[MAX_CLERKS]; /* Condition */
int _nextItem[MAX_CLERKS]; /* set to -1 for no more items */

int _customerWaitForTotalLock[MAX_CLERKS]; /* Lock */
int _customerWaitForTotalCV[MAX_CLERKS]; /* Condition */
int _clerkWaitForMoneyLock[MAX_CLERKS]; /* Lock */
int _clerkWaitForMoneyCV[MAX_CLERKS]; /* Condition */
int _customerWaitForReceiptLock[MAX_CLERKS]; /* Lock */
int _customerWaitForReceiptCV[MAX_CLERKS]; /* Condition */
int _clerkWaitForCustomerLeavingLock[MAX_CLERKS]; /* Lock */
int _clerkWaitForCustomerLeavingCV[MAX_CLERKS]; /* Condition */
int _orderTotal[MAX_CLERKS];
int _ammountPaid[MAX_CLERKS];
int _receipt[MAX_CLERKS]; /* boolean */
int _customerBeingHelped[MAX_CLERKS]; /* used for register to know what customer is being used */

int _registerLock[MAX_CLERKS]; /* Lock */
int _registerCV[MAX_CLERKS]; /* Condition */
int _toRegisterInteractionLock[MAX_CLERKS]; /* Lock */
int _toRegisterInteractionCV[MAX_CLERKS]; /* Condition */
int _fromRegisterInteractionLock[MAX_CLERKS]; /* Lock */
int _fromRegisterInteractionCV[MAX_CLERKS]; /* Condition */
UserItem _itemToScan[MAX_CLERKS];
UserItem _itemToRefund[MAX_CLERKS];
int _moneyToTransfer[MAX_CLERKS];

int _requestingTotal[MAX_CLERKS]; /* bool */
int _managerEmtpyingTill[MAX_CLERKS]; /* -1 is free, 1 is with clerk, 2 is with managment */
int _peopleWaitingForCashRegister[MAX_CLERKS];
int _peopleWaitingForCashRegiterLock[MAX_CLERKS]; /* Lock */
int _peopleWaitingForCashRegiterCV[MAX_CLERKS]; /* Condition */

int _customerActionLock; /* Lock */
int _customerWantsToScanItems[MAX_CLERKS]; /* true if wanting to scan the item, false if return */

int _occupancyLock; /* Lock */
int _storeDoorCV; /* Condition */
int _customersInStore;

int _testLocksLock;
int _testLocksMV;

int currentAisle;

void setupLocks() {
    currentAisle = 0;

    /* Populate things based on MAXIMUM_ITEMS */
    for(i = 0; i < MAX_ITEMS; i++) {
        if((i+1) % MAX_ITEMS_PER_AISLE == 0) {
            currentAisle ++;
        }
        itemsInStore[i]._itemId = i;
        itemsInStore[i]._aisle = currentAisle;
        itemsInStore[i]._price = 3*i + 1;
        itemsInStore[i]._quantity = 1;

        _shelfLock[i] = CreateLock("Shelf Lock"); /* Lock */
        _itemWaitCV[i] = CreateCV("Item Wait CV"); /* Condition */
        _itemStockOnShelf[i] = 0;
        _stockBoyReStockingItem[i] = NOT_FOUND;
        _customersWaitingForRestock[i] = 0;
    }

    /* Populate things that are not in a loop */
    _customerActionLock = CreateLock("Customer Action Lock"); /* Lock */

    _occupancyLock = CreateLock("Occupancy Lock"); /* Lock */
    _storeDoorCV = CreateCV("Store Door CV"); /* Condition */
    _customersInStore = 0;

    _clerkLinelock = CreateLock("Clerk Line Lock"); /* Lock */

    _registerNeedsMoney = CreateLock("Register Needs Money Lock"); /* Lock */
    _registersThatNeedMoney = 0;;

    _customerNeedsClerkAssitanceLock = CreateLock("Customer Needs Clerk Assistance Lock"); /* Lock */
    _customerNeedsClerkAssitanceCV = CreateCV("Customer Needs Clerk Assistance CV"); /* Condition */
    _customerShouldFindTheClerkCV = CreateCV("Customer Should Find The Clerk CV"); /* Condition */
    _customersNeedingAsistanceMV = 0; /* initial values set to zero */
    _clerkIDSignalingToCustomer = 0;

    _signalManagerClerkHelp = CreateLock("Signal Manager Clerk Help"); /* Lock */

    _clerksOnBreakLock = CreateLock("Clerks On Break Lock"); /* Lock */
    _clerksOnBreakCV = CreateCV("Clerks On Break CV"); /* Condition */
    _clerksOnBreakMV = 0; /* initial values set to zero */

    _stockBoyBreakLock = CreateLock("Stock Boy Break Lock"); /* Lock */
    _stockBoysOnBreakCV = CreateCV("Stock Boys On Break CV"); /* Condition */
    _stockBoyOnBreakMV = 0; /* initial values set to zero */

    _stockBoysStatusLock = CreateLock("Stock Boy Status Lock"); /* Lock */

    _stockRoomStatusLock = CreateLock("Stock Room Status Lock"); /* Lock */
    _stockRoomLock = CreateLock("Stock Room Lock"); /* Lock */
    _stockBoyIdInStockRoom = NOT_FOUND;
    _stockBoysWaitingForStockRoomCV = 0;
    _stockRoomCV = CreateCV("Stock Room CV"); /* Condition */
    _stockBoyOrderLock = CreateLock("Stock Boy Order Lock"); /* Lock */

    _customerWaitingForReStockLock = CreateLock("Customer Waiting for Restock Lock"); /* Lock */

    totalStoreSales = 0;


    _testLocksLock = CreateLock("Test Lock Lock");
    _testLocksMV = 0;

    /* Populate things based on MAX_CLERKS */
    for(i = 0; i < MAX_CLERKS; i++) {
        registerSales[i] = 0;

        _storeNeedsMoreClerks[i] = FALSE; /* false if lines are ok, true if a clerk saw a line > 4 */

        _registerNeedsMoneyCV[i] = CreateCV("Register Needs Money CV"); /* Condition */
        _moneyNeededForTill[i] = 0;
        _moneyGivenToTill[i] = 0;

        _clerkLineCV[i] = CreateLock("Clerk Line Lock"); /* CV for clerks */
        _clerkLineLength[i] = 0; /* Line length for each clerk */
        _clerkStatus[i] = CLERK_BUSY; /* MV for clerks - 0 is at register, 1 is on break */

        _clerkLock[i] = CreateLock("Clerk Lock"); /* Lock */
        _clerkCV[i] = CreateCV("Clerk CV"); /* Condition */
        _customerLock[i] = CreateLock("Customer Lock"); /* Lock */
        _customerCV[i] = CreateCV("Customer CV"); /* Condition */
        _ItemPassingClerkLock[i] = CreateLock("Item Passing Clerk Lock"); /* Lock */
        _ItemPassingClerkCV[i] = CreateCV("Item Passing Clerk CV"); /* Condition */
        _nextItem[i] = 0; /* set to -1 for no more items */

        _customerWaitForTotalLock[i] = CreateLock("Customer Wait For Total Lock"); /* Lock */
        _customerWaitForTotalCV[i] = CreateCV("Customer Wait For Total CV"); /* Condition */
        _clerkWaitForMoneyLock[i] = CreateLock("Clerk Wait For Money Lock"); /* Lock */
        _clerkWaitForMoneyCV[i] = CreateCV("Clerk Wait For Money CV"); /* Condition */
        _customerWaitForReceiptLock[i] = CreateLock("Customer Wait For Receipt Lock"); /* Lock */
        _customerWaitForReceiptCV[i] = CreateCV("Customer Wait For Receipt CV"); /* Condition */
        _clerkWaitForCustomerLeavingLock[i] = CreateLock("Clerk Wait Got Customer Leaving Lock"); /* Lock */
        _clerkWaitForCustomerLeavingCV[i] = CreateCV("Clerk Wait For Customer Leaving CV"); /* Condition */
        _orderTotal[i] = 0;
        _ammountPaid[i] = 0;
        _receipt[i] = FALSE; /* boolean */
        _customerBeingHelped[i] = 0; /* used for register to know what customer is being used */

        _registerLock[i] = CreateLock("Register Lock"); /* Lock */
        printf_3("Creating register CV ", i, "\n");
        _registerCV[i] = CreateCV("Create CV"); /* Condition */
        printf_3("id for that register was ", _registerCV[i], "\n");
        _toRegisterInteractionLock[i] = CreateLock("To Register Interaction Lock"); /* Lock */
        _toRegisterInteractionCV[i] = CreateCV("To Register Interaction CV"); /* Condition */
        _fromRegisterInteractionLock[i] = CreateLock("From Register Interaction Lock"); /* Lock */
        _fromRegisterInteractionCV[i] = CreateCV("From Register Interaction CV"); /* Condition */
        _itemToScan[i]._itemId = -1;
        _itemToScan[i]._aisle = -1;
        _itemToScan[i]._price = 0.0;
        _itemToScan[i]._quantity = -1;
        _itemToRefund[i]._itemId = -1;
        _itemToRefund[i]._aisle = -1;
        _itemToRefund[i]._price = 0.0;
        _itemToRefund[i]._quantity = -1;
        _moneyToTransfer[i] = 0;

        _requestingTotal[i] = FALSE; /* bool */
        _managerEmtpyingTill[i] = -2; /* -1 is free, 1 is with clerk, 2 is with managment */
        _peopleWaitingForCashRegister[i] = 0;
        _peopleWaitingForCashRegiterLock[i] = CreateLock("People Waiting For Cash Register Lock"); /* Lock */
        _peopleWaitingForCashRegiterCV[i] = CreateCV("People Waiting For Cash Register CV"); /* Condition */

        _customerWantsToScanItems[i] = TRUE; /* true if wanting to scan the item, false if return */

    }

    /* Populate things based on MAX_STOCKBOYS */
    for(i = 0; i < MAX_STOCKBOYS; i++) {
        _stockBoysStatus[i]; /* which Aisle we're in */

        _customerItemQuestionLock[i] = CreateLock("Customer Item Question Lock"); /* Lock */
        _customerItemQuestionMV[i] = NOT_FOUND;
        _customerID_AskingQuestionMV[i] = NOT_FOUND;
        _customerItemQuestionCV[i] = CreateCV("Customer Item Question CV"); /* Condition */

        _stockBoyAisleAnswerLock[i] = CreateLock("Stock Boy Aisle Answer Lock"); /* Lock */
        _stockBoyAisleAnswerMV[i] = NOT_FOUND;
        _stockBoyAisleAnswerCV[i] = CreateCV("Stock Boy Aisle Answer CV"); /* Condition */
    }

    /* Populate things based on NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS */
    for(i = 0; i < NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS; i++) {
        _customersWaitingInAisleToAskQuestionLock[i] = CreateLock("Customers Waiting In Aisle To Ask Question Lock"); /* Lock */
        _stockBoyIdInAisleToAnswerQuestionMV[i] = NOT_FOUND;
        _customersWaitingInAisleToAskQuestionMV[i] = 0;
        _customersWaitingInAisleToAskQuestionCV[i] = CreateCV("Customers Waiting In Aisle To Ask Question CV"); /* Condition */
    }

}






/* Data for Cash Register */
static int _cashRegisterLock;
static int _cashRegisterCounter;
int customerId;
int scan;
int registerId;
int registerStatusLock;
int registerInteractionLock;
int peopleWaitingCashLock;
int registerStatusCV;
int tmp;
int registerLock;
int scanning;
int returning;
int currentClerkId;
int tillBalance;
int currentCustomerBalance;
int currentItemCount;
UserItem itemPurchased;
UserItem itemRefunded;

void CashRegisterThread() {
    Acquire(_cashRegisterLock);
    customerId = _cashRegisterCounter;
    _cashRegisterCounter ++;
    Release(_cashRegisterLock);


    /* CashRegisterDoWork(customerId, customerId); */
    {
        registerId = customerId;
        currentClerkId = customerId;
        tillBalance = 0;
        currentCustomerBalance = 0;
        currentItemCount = 0;

        scan = TRUE;
        registerStatusLock = _registerLock[registerId];
        registerInteractionLock = _fromRegisterInteractionLock[registerId];
        peopleWaitingCashLock = _peopleWaitingForCashRegiterLock[registerId];
        registerStatusCV = _registerCV[registerId];

        /* printf_3("MY REGISTER CV ID = ", _registerCV[registerId], "\n"); */

        Acquire(registerStatusLock);

        _managerEmtpyingTill[registerId] = -1;

        while(TRUE) {
            if(_peopleWaitingForCashRegister[registerId] > 0) {
                #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                printf_5("CASH REGISTER #", registerId, " realizes there are ", _peopleWaitingForCashRegister[registerId], " people waiting for it. let one to start\n");
                #endif

                (_peopleWaitingForCashRegister[registerId])--;
                Signal(_peopleWaitingForCashRegiterCV[registerId], registerStatusLock);
            }
            #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                printf_3("CASH REGISTER #", registerId, " waiting for people to start interacting\n");
            #endif

            Wait(registerStatusCV, registerStatusLock);

            #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                printf_3("CASH REGISTER #", registerId, " Just got a signal\n");
            #endif

            if(_managerEmtpyingTill[registerId] == 0) {
                Release(registerStatusLock);

                #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                    printf_3("CASH REGISTER #", registerId, " start interacting with a clerk\n");
                #endif

                Acquire(registerInteractionLock);

                #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                    printf_3("CASH REGISTER #", registerId, " clerk wants to scan items\n");
                #endif

                /* InteractWithClerk(cashRegister); */
                {
                    scanning = TRUE;
                    /* reset totals */
                    currentItemCount = 0;
                    currentCustomerBalance = 0;
                    /* wake up clerk and tell him we're ready for items */
                    registerLock = _fromRegisterInteractionLock[registerId];

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_3("CASH REGISTER #", registerId, " let the clerk know we are ready for next item\n");
                    #endif

                    Signal(_fromRegisterInteractionCV[registerId], registerLock);

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_3("CASH REGISTER #", registerId, " wait till next item be scanned\n");
                    #endif

                    Wait(_toRegisterInteractionCV[registerId], registerLock);

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_3("CASH REGISTER #", registerId, " clerk just woke us up\n");
                    #endif

                    itemPurchased = _itemToScan[registerId];
                    itemRefunded = _itemToRefund[registerId];
                    returning = FALSE;

                    while(itemPurchased._itemId != NOT_FOUND || itemRefunded._itemId != NOT_FOUND) {
                        if(itemPurchased._itemId != NOT_FOUND) {
                            #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                                printf_7("Cash Register [", registerId, "] got item [", itemPurchased._itemId, "] from Clerk [", registerId, "] to scan.\n");
                            #endif

                            currentCustomerBalance += itemPurchased._price;
                            _itemToScan[registerId]._itemId = NOT_FOUND;
                            currentItemCount++;
                        } else if (itemRefunded._itemId != NOT_FOUND) {
                            returning = TRUE;

                            #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                                printf_7("Cash Register [", registerId, "] got item [", itemRefunded._itemId, "] from Clerk [", registerId, "] to scan.\n");
                            #endif

                            currentCustomerBalance -= itemRefunded._price;
                            _itemToRefund[registerId]._itemId = NOT_FOUND;
                            currentItemCount++;
                        }
                        #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                            printf_3("CASH REGISTER #", registerId, " let the clerk know we are ready for next item\n");
                        #endif

                        Signal(_fromRegisterInteractionCV[registerId], registerLock);

                        #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                            printf_3("CASH REGISTER #",  registerId, " wait till next item be scanned\n");
                        #endif

                        Wait(_toRegisterInteractionCV[registerId], registerLock);

                        #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                            printf_3("CASH REGISTER #", registerId, " clerk just woke us up\n");
                        #endif

                        itemPurchased = _itemToScan[registerId];
                        itemRefunded = _itemToRefund[registerId];
                    }
                    /* All (or no) items have been scanned. Lets put the totals into */
                    /* the shared variable and let the clerk know that he can grab it */
                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_7("Cash Register [", registerId, "] has scanned all [", currentItemCount, "] items for Customer [", _customerBeingHelped[registerId] , "].\n");
                    #endif

                    _moneyToTransfer[registerId] = currentCustomerBalance;

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_11("Cash Register [", registerId, "] gave total cost $[", currentCustomerBalance, "] for Customer [", _customerBeingHelped[registerId] , "] to Clerk[", registerId, "] for [", currentItemCount, "] items.\n");
                    #endif

                    Signal(_fromRegisterInteractionCV[registerId], registerLock);

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_3("CASH REGISTER #", registerId , " lets wait till we receive/pay the money\n");
                    #endif

                    Signal(_toRegisterInteractionCV[registerId], registerLock);

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        if(returning) {
                            printf_5("Cash Register [", registerId, "] gave the money to Clerk [", registerId, "].\n");
                        } else {
                            printf_5("Cash Register [", registerId, "] got the money from Clerk [", registerId, "].\n");
                        }
                    #endif

                    /* Customer paid/received the money, lets print receipt */
                    tillBalance += currentCustomerBalance;

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_3("CASH REGISTER #", registerId, " is printing receipt.\n");
                    #endif

                    Signal(_fromRegisterInteractionCV[registerId], registerLock);

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_7("Cash Register [", registerId, "] gave receipt to Clerk [", registerId, "] for Customer[", _customerBeingHelped[registerId], "].\n");
                    #endif
                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_5("Cash Register [", registerId, "] total sale is $[", (registerSales[registerId])+tillBalance, "].\n");
                    #endif

                    Release(registerLock);
                }
                Release(registerInteractionLock);

            } else if(_managerEmtpyingTill[registerId] == 1) {
                Release(registerStatusLock);

                #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                    printf_3("CASH REGISTER #", registerId, " start interacting with manager\n");
                #endif

                Acquire(registerInteractionLock);

                #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                    printf_3("CASH REGISTER #", registerId, " manager wants to empty till \n");
                #endif

                /* InteractWithManager(cashRegister); */
                {
                    /* wake up the manager and tell him the total of the till */
                    registerLock = _fromRegisterInteractionLock[registerId];

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_5("CASH REGISTER #", registerId, " let the manager know that total till is ", tillBalance, "\n");
                    #endif

                    _moneyToTransfer[registerId] = tillBalance;
                    Signal(_fromRegisterInteractionCV[registerId], registerLock);

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_3("CASH REGISTER #", registerId, " wait till manager picks up the till content\n");
                    #endif

                    Wait(_toRegisterInteractionCV[registerId], registerLock);

                    /* Increase Sales */
                    (registerSales[registerId]) += tillBalance;
                    tillBalance = 0;

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_3("Cash Register [", registerId, "] drawer has emptied by Manager.\n");
                    #endif
                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        printf_5("Cash Register [", registerId, "] total sale until now is $[", (registerSales[registerId]) , "].\n");
                    #endif
                }
                Release(registerInteractionLock);
            }
            Acquire(registerStatusLock);
            _managerEmtpyingTill[registerId] = -1;
            for(tmp = 0; tmp < 10; tmp++) {
                Yield();
            }

        }
        Release(registerStatusLock);
    }
    Exit(0);
}


static int _counterLock;
static int _clerkCounter;
int clerkId;
int clerkLock;
int registerLock;
int registerStatusLock;
int peopleWaiting;
int totalItemsProvidedCount;
int itemIdpassed;
int totalTransactionAmount;
int currentRegister;
int customerWantsToReturn;
int waitForClerksToReturn;
int totalSignaled;
int haveAJob;
int currentRegister;
void ClerkThread() {
    Acquire(_counterLock);
    customerId = _clerkCounter;
    _clerkCounter ++;
    Release(_counterLock);

    /* GoToWork(_clerkCounter); */
    {
        haveAJob = TRUE;

        currentRegister = _clerkCounter;

        while(haveAJob == TRUE) {
            /* Make sure no one can get in line while we help our customer */
            #ifdef PRINT_LOCKS_CLERK
                printf_3("CLERK# ", currentRegister, " clerkLineLock->Acquire()\n");
            #endif

            Acquire(_clerkLinelock);

            #ifdef PRINT_LOCKS_CLERK
                printf_3("CLERK# ", currentRegister, " clerkLineLock->Acquire() Done!\n");
            #endif

            if(_clerkLineLength[currentRegister] > 0) {
                #ifdef PRINT_EXTRA_LOG_CLERK
                    printf_5("CLERK# ", currentRegister, " : founds out there are ", _clerkLineLength[currentRegister], " customers waiting for him \n");
                #endif

                /* I have some customers in my line */
                if(_clerkLineLength[currentRegister] > 4) {
                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("Clerk [", currentRegister, "] see more than 4 people in line and calls Manager.\n");
                    #endif
                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("CLERK# ", currentRegister, " _signalManagerClerkHelp->Acquire()\n");
                    #endif

                    Acquire(_signalManagerClerkHelp);

                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("CLERK# ", currentRegister, " _signalManagerClerkHelp->Acquire() Done!\n");
                    #endif

                    _storeNeedsMoreClerks[currentRegister] = TRUE;

                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("CLERK# ", currentRegister, " _signalManagerClerkHelp->Release()\n");
                    #endif

                    Release(_signalManagerClerkHelp);

                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("CLERK# ", currentRegister, " _signalManagerClerkHelp->Release() Done!\n");
                    #endif
                }

                #ifdef PRINT_LOCKS_CLERK
                    printf_5("CLERK# ", currentRegister, " _clerkLine[", currentRegister, "][clerkLineLock]->Signal()\n");
                #endif

                Signal(_clerkLineCV[currentRegister], _clerkLinelock);
                _clerkLineLength[currentRegister]--;
                clerkLock = _clerkLock[currentRegister];

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLock->Acquire()\n");
                #endif

                Acquire(clerkLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLock->Acquire() Done!\n");
                #endif
                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLineLock->Release()\n");
                #endif

                Release(_clerkLinelock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLineLock->Release() Done!\n");
                #endif

                /* The customer is in sleep, waiting for our signal so he can */
                /* provide his information (returning or purchase) */
                #ifdef PRINT_EXTRA_LOG_CLERK
                    printf_3("CLERK# ", currentRegister, " : Waits till customer tell him he is ready to pass the items\n");
                #endif
                #ifdef PRINT_LOCKS_CLERK
                    printf_5("CLERK# ", currentRegister, " clerkCV[", currentRegister, "][clerkLock]->Wait()\n");
                #endif

                Wait(_clerkCV[currentRegister], clerkLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_5("CLERK# ", currentRegister, " clerkCV[", currentRegister, "][clerkLock]->Wait() Done!\n");
                #endif

                /* Customer just signaled us that he is ready to pass */
                /* the items to us */
                #ifdef PRINT_EXTRA_LOG_CLERK
                    printf_3("CLERK# ", currentRegister, " : Customer announced he is read to pass the items\n");
                #endif

                Acquire(_customerActionLock);
                customerWantsToReturn = _customerWantsToScanItems[currentRegister];
                Release(_customerActionLock);

                /* HelpCustomerCheckout(clerk, customerWantsToReturn); */
                {
                    /* currentRegister = clerk.currentRegister; */

                    clerkLock = _clerkLock[currentRegister];
                    registerLock = _fromRegisterInteractionLock[currentRegister];
                    registerStatusLock = _registerLock[currentRegister];

                    #ifndef IGNORE_REGISTERS
                    { /* Braces to show scope change for IGNORE_REGISTERS */
                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, " :Lets acquire the register\n");
                        #endif

                        Acquire(registerStatusLock);

                        while(_managerEmtpyingTill[currentRegister] != -1 ||
                              _peopleWaitingForCashRegister[currentRegister] > 0) {
                            /* Cash register hasn't started to work yet */
                            /* lets wait for it to startup */
                            #ifdef PRINT_EXTRA_LOG_CLERK
                                printf_3("CLERK# ", currentRegister, " :Cash regiter is busy, lets wait\n");
                            #endif

                            peopleWaiting = _peopleWaitingForCashRegiterLock[currentRegister];
                            Acquire(peopleWaiting);

                            (_peopleWaitingForCashRegister[currentRegister])++;

                            Release(registerStatusLock);

                            Wait(_peopleWaitingForCashRegiterCV[currentRegister],registerStatusLock);

                            Acquire(registerStatusLock);
                            Release(peopleWaiting);
                        }
                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, " :Let the register know we want to scan items\n");
                        #endif

                        Signal(_registerCV[currentRegister],registerStatusLock);

                        Acquire(registerLock);

                        _managerEmtpyingTill[currentRegister] = 0;

                        Release(registerStatusLock);

                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, " :Lets wait for cash regiter until it is ready\n");
                        #endif

                        /* Lets wait for cash register till announce it is ready to accept items */
                        Wait(_fromRegisterInteractionCV[currentRegister], registerLock);
                        /* Register is ready to accept our items. */

                    } /* end braces to show scope change for IGNORE_REGISTERS */
                    #endif

                    totalItemsProvidedCount = 0;
                    while(_nextItem[currentRegister] != NOT_FOUND) {
                        itemIdpassed = _nextItem[currentRegister];
                        totalItemsProvidedCount++;

                        #ifdef PRINT_OUTPUT_CLERK
                            printf_7("Clerk ", currentRegister, " got item [", itemIdpassed, "] from Customer [", _customerBeingHelped[currentRegister], "].\n");
                        #endif

                        #ifndef IGNORE_REGISTERS
                        { /* Braces to show scope change for IGNORE_REGISTERS */
                            /* Lets put the item into the cash register */
                            if(customerWantsToReturn) {
                                _itemToRefund[currentRegister] = itemsInStore[itemIdpassed];
                            } else {
                                _itemToScan[currentRegister] = itemsInStore[itemIdpassed];
                            }

                            Signal(_toRegisterInteractionCV[currentRegister], registerLock);

                            /* Lets wait for cash register till announces it is ready to accept items */
                            #ifdef PRINT_OUTPUT_CLERK
                                printf_7("Clerk ", currentRegister, " gave item [", itemIdpassed, "] to Cash Register [", currentRegister, "] for scanning.\n");
                            #endif

                            Wait(_fromRegisterInteractionCV[currentRegister], registerLock);
                        } /* end braces to show scope change for IGNORE_REGISTERS */
                        #endif

                        Signal(_customerCV[currentRegister], clerkLock);

                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, ": Lets wait for the next item.\n");
                        #endif

                        Wait(_clerkCV[currentRegister], clerkLock);

                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, " : Customer just signaled that the next item is ready\n");
                        #endif
                    }

                    #ifdef PRINT_EXTRA_LOG_CLERK
                        if (totalItemsProvidedCount == 0) {
                            printf_3("CLERK# ", currentRegister, " : Customer hasn't passed any items.\n");
                        } else {
                            printf_3("CLERK# ", currentRegister, " : Customer has passed all of his items.\n");
                        }
                    #endif
                    #ifdef PRINT_EXTRA_LOG_CLERK
                        printf_3("CLERK# ", currentRegister, " : Get the totals from cash register\n");
                    #endif

                    /* Now we need to calculate the total */
                    totalTransactionAmount = 0;

                    #ifndef IGNORE_REGISTERS
                    { /* Braces to show scope change for IGNORE_REGISTERS */
                        _itemToRefund[currentRegister]._itemId = NOT_FOUND;
                        _itemToScan[currentRegister]._itemId = NOT_FOUND;

                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, " signal cash register to give us the total\n");
                        #endif

                        Signal(_toRegisterInteractionCV[currentRegister], registerLock);

                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, " wait for cash register till it calculates the total amount\n");
                        #endif

                        Wait(_fromRegisterInteractionCV[currentRegister], registerLock);

                        /* Grab the total from the cash register */
                        totalTransactionAmount = _moneyToTransfer[currentRegister];

                    } /* end braces to show scope change for IGNORE_REGISTERS */
                    #endif

                    #ifdef PRINT_EXTRA_LOG_CLERK
                        printf_7("Clerk [", currentRegister, "] got total cost $[", totalTransactionAmount, "] from Cash Register [", currentRegister, "].\n");
                    #endif

                    /* Signal the customer to pay/receive the money */
                    Signal(_customerCV[currentRegister], clerkLock);

                    /* Wait till customer pays his bill or pickup his refund */
                    #ifdef PRINT_EXTRA_LOG_CLERK
                        printf_7("Clerk [", currentRegister, "] tells Customer [", _customerBeingHelped[currentRegister], "] total cost is $[", totalTransactionAmount, "].\n");
                    #endif

                    Wait(_clerkCV[currentRegister], clerkLock);

                    /* Pickup the money paid */
                    #ifdef PRINT_OUTPUT_CLERK
                        if (customerWantsToReturn) {
                                printf_7("Clerk [", currentRegister, "] got money [", totalTransactionAmount, "] from Cash Register [", currentRegister, "].\n");
                        } else {
                                printf_7("Clerk [", currentRegister, "] got money [", totalTransactionAmount, "] from Customer [", _customerBeingHelped[currentRegister], "].\n");
                        }
                    #endif

                    /* Wait for the receipt from the cash register */
                    #ifndef IGNORE_REGISTERS
                    { /* Braces to show scope change for IGNORE_REGISTERS */
                        /* Let the cash register know the amount was processed */
                        /* and receipt is required */
                        Signal(_toRegisterInteractionCV[currentRegister], registerLock);

                        #ifdef PRINT_OUTPUT_CLERK
                            if (customerWantsToReturn) {
                                printf_7("Clerk [", currentRegister, "] gave money [", totalTransactionAmount, "] to Customer [", _customerBeingHelped[currentRegister], "].\n");
                            } else {
                                printf_7("Clerk [", currentRegister, "] gave money [", totalTransactionAmount, "] to Cash Register [", currentRegister, "].\n");
                            }
                        #endif

                        Wait(_fromRegisterInteractionCV[currentRegister], registerLock);

                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_5("Clerk [", currentRegister, "] got receipt from Cash Register[", currentRegister, "].\n");
                        #endif
                    } /* end braces to show scope change for IGNORE_REGISTERS */
                    #endif

                    /* And let the customer know he can pickup the receipt */
                    Signal(_customerCV[currentRegister], clerkLock);

                    /* Wait till customer pickup the receipt (and payment if it was a refund) */
                    #ifdef PRINT_OUTPUT_CLERK
                        printf_5("Clerk [", currentRegister, "] gave the receipt to Customer [", _customerBeingHelped[currentRegister], "] and tells him to leave.\n");
                    #endif
                    #ifdef PRINT_EXTRA_LOG_CLERK
                        printf_3("CLERK# ", currentRegister, " : Wait till customer picks up the receipt\n");
                    #endif

                    Wait(_clerkCV[currentRegister], clerkLock);

                    /* We are done with this customer, lets release our lock */
                    #ifdef PRINT_EXTRA_LOG_CLERK
                        printf_3("CLERK# ", currentRegister, " : Done with this customer!!!\n");
                    #endif

                    #ifndef IGNORE_REGISTERS
                    { /* Braces to show scope change for IGNORE_REGISTERS */
                        #ifdef PRINT_EXTRA_LOG_CLERK
                            printf_3("CLERK# ", currentRegister, " :Release the register lock\n");
                        #endif

                        Release(registerLock);
                    } /* end braces to show scope change for IGNORE_REGISTERS */
                    #endif
                }

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLock->Release()!\n");
                #endif

                Release(clerkLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLock->Release() Done!\n");
                #endif

                haveAJob = TRUE;
            } else {
                /* time to go on break - all clerks are allowed to go on break */
                #ifdef PRINT_OUTPUT_CLERK
                    printf_3("Clerk [", currentRegister, "] is leaving Cash Register [\n");
                    /* printf_5("Clerk [", currentRegister, "] is leaving Cash Register [", currentRegister, "] and going on break.\n"); */
                #endif

                /* set our status to on break */
                _clerkStatus[currentRegister] = CLERK_BREAK;

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLineLock->Release()!\n");
                #endif

                Release(_clerkLinelock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkLineLock->Release() Done!\n");
                #endif
                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkOnBreakLock->Acquire()!\n");
                #endif

                /* get the going on break lock */
                Acquire(_clerksOnBreakLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkOnBreakLock->Acquire() Done!\n");
                #endif

                /* increment the number of clerks on break */
                _clerksOnBreakMV ++;

                /* wait to be woken up */
                #ifdef PRINT_EXTRA_LOG_CLERK
                    printf_3("CLERK# ", currentRegister, " : Wait for manager to wake me up\n");
                #endif
                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerksOnBreakCV->Wait()\n");
                #endif

                Wait(_clerksOnBreakCV, _clerksOnBreakLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerksOnBreakCV->Wait() Done!\n");
                #endif

                /* we're no longer on break, lets get busy! */
                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerksLineLock->Acquire()\n");
                #endif

                Acquire(_clerkLinelock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerksLineLock->Acquire() Done!\n");
                #endif

                _clerkStatus[currentRegister] = CLERK_BUSY;

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerksLineLock->Release()\n");
                #endif

                Release(_clerkLinelock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerksLineLock->Release done!()\n");
                #endif
                #ifdef PRINT_OUTPUT_CLERK
                    printf_3("Clerk [", currentRegister, "] was called by Manager to work.\n");
                #endif

                waitForClerksToReturn = _customerNeedsClerkAssitanceLock;

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " ClerkOnBreakLock->Release()\n");
                #endif

                Release(_clerksOnBreakLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " clerkOnBreakLock->Release() done!\n");
                #endif
                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " waitForClerksToReturn->Acquire()\n");
                #endif

                Acquire(waitForClerksToReturn);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CLERK# ", currentRegister, " waitForClerksToReturn->Acquire() Done!\n");
                #endif

                /* See if any customer was waiting for us */
                #ifdef PRINT_EXTRA_LOG_CLERK
                    printf_3("CLERK# ", currentRegister, " : Just got back from break.\n");
                #endif

                totalSignaled = 0;
                while (_customersNeedingAsistanceMV > 0 && totalSignaled < 5) {
                    Signal(_customerNeedsClerkAssitanceCV, waitForClerksToReturn);
                    _customersNeedingAsistanceMV --;
                    _clerkIDSignalingToCustomer = currentRegister;
                    totalSignaled++;

                    #ifdef PRINT_EXTRA_LOG_CLERK
                        printf_3("CLERK# ", currentRegister, " : Just signaled a client to wake up.\n");
                    #endif

                    Wait(_customerShouldFindTheClerkCV, waitForClerksToReturn);

                    #ifdef PRINT_EXTRA_LOG_CLERK
                        printf_3("CLERK# ", currentRegister, " : client asnwered back that he is in line\n");
                    #endif
                }
                #ifdef PRINT_EXTRA_LOG_CLERK
                    printf_5("CLERK# ", currentRegister, " : Just signaled ", totalSignaled, " customers to come into line\n");
                #endif

                Release(waitForClerksToReturn);
            }
        }
    }
    Exit(0);
}


static int _stockBoyLock;
static int stockBoyCounter;
int stockBoyId;
int stockBoysBreakLock;
int customersWaiting;
int questionLock;
int answerLock;
int stockBoysStatus;
int itemIDQuestioned;
int customerIDasking;
int aisleIDAns;
int stockRoomLock;
int justWokeup;
int itemIdToBeReStocked;
int reStockLock;
int currentAisleIndex;
int itemLock;
int aisleID;
int _stockBoyIndex;
void StockBoyThread() {
    Acquire(_stockBoyLock);
    stockBoyId = stockBoyCounter;
    stockBoyCounter++;
    Release(_stockBoyLock);

    /* StockBoyDoWork(stockBoyId); */
    {
        _stockBoyIndex = stockBoyId;

        /* locks = theLocksInHomeDepot; */

        /* We are currently unavailable */
        /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
        Acquire(_stockBoysStatusLock);
        _stockBoysStatus[stockBoyId] = -1;
        Release(_stockBoysStatusLock);

        stockRoomLock = _stockRoomLock;
        justWokeup = TRUE;

        while(TRUE == TRUE) {
            /* lets see if we need to re stock an item */
            /* _stockBoyOrderLock->Acquire(); */
            itemIdToBeReStocked = NOT_FOUND;

            /* _stockBoyReStockingItem */
            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                printf_3("StockBoy [", stockBoyId, " lets see if any body needs restocking.\n");
            #endif

            reStockLock = _customerWaitingForReStockLock;

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire()\n");
            #endif

            Acquire(reStockLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire() Done!\n");
            #endif

            for (i=0; i< MAX_ITEMS; i++) {
                if (_customersWaitingForRestock[i] > 0 && _stockBoyReStockingItem[i] == NOT_FOUND) {
                    itemIdToBeReStocked = i;
                    _stockBoyReStockingItem[i] = stockBoyId;
                    break;
                }
            }

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Release()\n");
            #endif

            Release(reStockLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                printf_3("StockBoy #", stockBoyId, " reStockLock->Release() Done!\n");
            #endif

            if (itemIdToBeReStocked != NOT_FOUND) {
                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " finds out item#", itemIdToBeReStocked, " needs to be re stock\n");
                #endif

                if (justWokeup == FALSE) {
                    #ifdef PRINT_OUTPUT_STOCKBOY
                        printf_5("StockBoy [", stockBoyId, "] goes back to Stock room for item [", itemIdToBeReStocked, "]\n");
                    #endif
                }

                /* i need to re stock, lets acquire the storage room */
                Acquire(_stockRoomStatusLock);

                while (_stockBoyIdInStockRoom != NOT_FOUND) {
                    _stockBoysWaitingForStockRoomCV ++;

                    #ifdef PRINT_OUTPUT_STOCKBOY
                        printf_5("StockBoy [", stockBoyId, "] is waiting for StockBoy [", _stockBoyIdInStockRoom, "] to leave the Stock Room.\n");
                    #endif

                    Wait(_stockRoomCV, _stockRoomStatusLock);
                }

                #ifdef PRINT_OUTPUT_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] is in stock room\n");
                #endif

                _stockBoyIdInStockRoom = stockBoyId;
                Release(_stockRoomStatusLock);

                /* Now we are at stock room, we grab supplies and will get out of the room */
                /* so other stock boys can use it, */

                /* PickupSuppliesFromStorage(stockboy, itemIdToBeReStocked); */
                {
                    /* We already have acquired the lock for storage */
                    /* in previous. Section. No additional code required in here because we know we can */
                    /* pick up as many as required. */
                    for (i = 1; i< 10; i++) {
                        Yield();
                    }
                    #ifdef PRINT_OUTPUT_STOCKBOY
                        printf_5("StockBoy [", stockBoyId, "] retrieves one new item [", itemIdToBeReStocked, "] from stock room.\n");
                    #endif
                }

                /*
                 * Before leaving stock room we have to tell other stock boys that the next one can enter the stock room
                 */

                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " is going to tell everyone he is leaving\n");
                #endif

                Acquire(_stockRoomStatusLock);
                _stockBoyIdInStockRoom = NOT_FOUND;

                if (_stockBoysWaitingForStockRoomCV > 0) {
                    #ifdef PRINT_EXTRA_LOG_STOCKBOY
                        printf_3("StockBoy #", stockBoyId, " find outs people are waiting for him, signal them to come in.\n");
                    #endif

                    _stockBoysWaitingForStockRoomCV --;
                    Signal(_stockRoomCV, _stockRoomStatusLock);
                }

                #ifdef PRINT_OUTPUT_STOCKBOY
                    printf_3("StockBoy [", stockBoyId, "] leaves stock room\n");
                #endif

                Release(_stockRoomStatusLock);

                /* By now we have got the supplies from stock room, locked the item, and can re stock it */
                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " is querying the aisle of item#", itemIdToBeReStocked, "\n");
                #endif

                /* currentAisleIndex = GetAisleNumber(getStoreInstance(), itemIdToBeReStocked); */
                currentAisleIndex = itemsInStore[itemIdToBeReStocked]._aisle;

                /* ASSERT(currentAisleIndex >= 0 && currentAisleIndex < MAX_AISLES); */
                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_7("StockBoy #", stockBoyId, " found out the aisle#", currentAisleIndex, " of item#", itemIdToBeReStocked, "\n");
                #endif

                /* Lets go to its aisle. Set Status to current aisle */
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " Set stock boy status()\n");
                #endif

                /* SetStockBoysStatus(stockboy, stockBoyId, currentAisleIndex); */
                Acquire(_stockBoysStatusLock);
                _stockBoysStatus[stockBoyId] = currentAisleIndex;
                Release(_stockBoysStatusLock);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " Set stock boy status() Done!\n");
                #endif
                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " is in the aisle#", currentAisleIndex, "\n");
                #endif

                /* but first we need to lock the item */
                /* so no other stock boy or customer can manipulate its values while we are */
                /* re stocking it. */
                itemLock  = _shelfLock[itemIdToBeReStocked];

                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " needs to lock the item#", itemIdToBeReStocked, " first in order to restock it\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Lock()\n");
                #endif

                Acquire(itemLock);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Lock()\n");
                #endif

                /* Re stock the item */
                /* RestockItem(theStoreInHomeDepot, itemIdToBeReStocked); */
                itemsInStore[itemIdToBeReStocked]._quantity ++;

                printf_3("Current number of Item I jsut restocked is now", itemsInStore[itemIdToBeReStocked]._quantity , "\n");

                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " ReStcoked the item# ", itemIdToBeReStocked, "\n");
                    /* let the waiting customers know that the item is available */
                    printf_5("StockBoy #", stockBoyId, " lets wake up people who are waiting for this item#", itemIdToBeReStocked, "\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Release()\n");
                #endif

                Release(itemLock);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_5("StockBoy #", stockBoyId, " item#", itemIdToBeReStocked, " Release() Done!\n");
                #endif
                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire()\n");
                #endif

                Acquire(reStockLock);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " reStockLock->Acquire() Done!\n");
                #endif

                if (_customersWaitingForRestock[itemIdToBeReStocked] > 0) {
                    #ifdef PRINT_EXTRA_LOG_STOCKBOY
                        printf_5("StockBoy #", stockBoyId, " Currently ", _customersWaitingForRestock[itemIdToBeReStocked], " customers are waiting for this item. Signal one of them.\n");
                    #endif

                    _customersWaitingForRestock[itemIdToBeReStocked]--;

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_5("StockBoy #", stockBoyId, " itemWaitCV[", itemIdToBeReStocked, "]->Signal()\n");
                    #endif

                    Signal(_itemWaitCV[itemIdToBeReStocked], reStockLock);
                }

                _stockBoyReStockingItem[itemIdToBeReStocked] = NOT_FOUND;

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " reStockLock->Release()\n");
                #endif

                Release(reStockLock);

                #ifdef PRINT_LOCKS_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " reStockLock->Release() Done!\n");
                #endif

                /* _stockBoyOrderLock->Release(); */
                /* We are walking in aisle; yield to the coming customers */
                /* so they have an opportunity to ask their questions. */
                for (i = 0; i < STOCKBOY_DELAY; i++) {
                    Yield();
                }

                /* OK. we have re-stocked an item, lets see if there are any customers in this */
                /* aisle who need help. */
                /* lets see if any customer has any question in current aisle. */
                /* AnswerQuestionsOfCustomers(stockboy, currentAisleIndex); */
                {
                    aisleID = currentAisleIndex;
                    customersWaiting = _customersWaitingInAisleToAskQuestionLock[aisleID];
                    questionLock = _customerItemQuestionLock[stockBoyId];
                    answerLock = _stockBoyAisleAnswerLock[stockBoyId];
                    stockBoysStatus = _stockBoysStatusLock;

                    /* Check for customers needing help. - Customers will find StockBoys at any aisle, at any time. */
                    /*                                   - the Customer has no way of knowing when the stock boy will be ready to help them which */
                    /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                    Acquire(_stockBoysStatusLock);
                    _stockBoysStatus[stockBoyId] = -1;
                    Release(_stockBoysStatusLock);

                    #ifdef PRINT_EXTRA_LOG_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " lets see if any body has any questions\n");
                    #endif
                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customersWaiting->Acquire()\n");
                    #endif

                    Acquire(customersWaiting);

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customersWaiting->Acquire() Done!\n");
                    #endif

                    if(_stockBoyIdInAisleToAnswerQuestionMV[aisleID] == NOT_FOUND &&
                       _customersWaitingInAisleToAskQuestionMV[aisleID] > 0) {

                        _stockBoyIdInAisleToAnswerQuestionMV[aisleID] = stockBoyId;
                        while (_customersWaitingInAisleToAskQuestionMV[aisleID] > 0 ){
                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_7("StockBoy [", stockBoyId, " finds out there are ", _customersWaitingInAisleToAskQuestionMV[aisleID], " customers waiting to ask question in Aisle#", aisleID, "lock.\n");
                            #endif
                            /* There is a customer needing help */
                            /* The stock boy must change their state so that a customer knows that they are ready to help in the customer's aisle */
                            /* SetStockBoysStatus(_stockBoyIndex, aisleID + NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS); */
                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " sets his status to #", aisleID+NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS, " and signals so customers waiting in this aisle realize he is willing to help.\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " customersWaiting[customersWaiting][", aisleID, "]->Signal()\n");
                            #endif

                            Signal(_customersWaitingInAisleToAskQuestionCV[aisleID], customersWaiting);
                            _customersWaitingInAisleToAskQuestionMV[aisleID]--;
                            /* Now the customer can ask his/her question. */
                            /* Lets wait to receive the Item Number */

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Acquire()\n");
                            #endif

                            Acquire(questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customersWaiting->Release()\n");
                            #endif

                            Release(customersWaiting);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customersWaiting->Release() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Wait()\n");
                            #endif

                            Wait(_customerItemQuestionCV[stockBoyId], questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Wait()\n Done!");
                            #endif

                            itemIDQuestioned = _customerItemQuestionMV[stockBoyId];
                            customerIDasking = _customerID_AskingQuestionMV[stockBoyId];

                            #ifdef PRINT_OUTPUT_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, "] is approached by Customer [", customerIDasking, "] for assistance.\n");
                            #endif
                            /* Lets answer the question asked */
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " Answer[", stockBoyId, "]->Acquire()\n");
                            #endif

                            Acquire(answerLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " Answer[", stockBoyId, "]->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Release()\n");
                            #endif

                            Release(questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Release() Done\n");
                            #endif

                            /* aisleIDAns = GetAisleNumber(theStoreInHomeDepot, itemIDQuestioned); */
                            {
                                aisleIDAns = itemsInStore[itemIDQuestioned]._aisle;
                            }

                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_7("StockBoy [", stockBoyId, " the aisle ID for item#", itemIDQuestioned, " is #", aisleIDAns, "\n");
                            #endif

                            _stockBoyAisleAnswerMV[stockBoyId] = aisleIDAns;

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answerCV[", stockBoyId, "][answerLock]->Signal()\n");
                            #endif

                            Signal(_stockBoyAisleAnswerCV[stockBoyId], answerLock);

                            #ifdef PRINT_OUTPUT_STOCKBOY
                                printf_9("StockBoy [", stockBoyId, "] gave aisle [", aisleIDAns, "] to Customer [", customerIDasking, "] for item [", itemIDQuestioned, "]\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customerWaiting->Acquire()\n");
                            #endif

                            Acquire(customersWaiting);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customerWaiting->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answer[", stockBoyId, "]->Release()\n");
                            #endif

                            Release(answerLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answer[", stockBoyId, "]->Release Done!()\n");
                            #endif
                        }
                        _stockBoyIdInAisleToAnswerQuestionMV[aisleID] = NOT_FOUND;
                    }

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customerWaiting->Release()\n");
                    #endif

                    Release(customersWaiting);

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customerWaiting->Release() Done!\n");
                    #endif
                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " stockBoyStatus->Acquire()\n");
                    #endif

                    /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                    Acquire(_stockBoysStatusLock);
                    _stockBoysStatus[stockBoyId] = -1;
                    Release(_stockBoysStatusLock);
                }

                /* lets see if any customer has any question in service area. */
                /* AnswerQuestionsOfCustomers(stockboy, SERVICE_AREA_LINE); */
                {
                    aisleID = currentAisleIndex;
                    customersWaiting = _customersWaitingInAisleToAskQuestionLock[aisleID];
                    questionLock = _customerItemQuestionLock[stockBoyId];
                    answerLock = _stockBoyAisleAnswerLock[stockBoyId];
                    stockBoysStatus = _stockBoysStatusLock;

                    /* Check for customers needing help. - Customers will find StockBoys at any aisle, at any time. */
                    /*                                   - the Customer has no way of knowing when the stock boy will be ready to help them which */
                    /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                    Acquire(_stockBoysStatusLock);
                    _stockBoysStatus[stockBoyId] = -1;
                    Release(_stockBoysStatusLock);

                    #ifdef PRINT_EXTRA_LOG_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " lets see if any body has any questions\n");
                    #endif
                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customersWaiting->Acquire()\n");
                    #endif

                    Acquire(customersWaiting);

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customersWaiting->Acquire() Done!\n");
                    #endif

                    if(_stockBoyIdInAisleToAnswerQuestionMV[aisleID] == NOT_FOUND &&
                       _customersWaitingInAisleToAskQuestionMV[aisleID] > 0) {

                        _stockBoyIdInAisleToAnswerQuestionMV[aisleID] = stockBoyId;
                        while (_customersWaitingInAisleToAskQuestionMV[aisleID] > 0 ){
                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_7("StockBoy [", stockBoyId, " finds out there are ", _customersWaitingInAisleToAskQuestionMV[aisleID], " customers waiting to ask question in Aisle#", aisleID, "lock.\n");
                            #endif
                            /* There is a customer needing help */
                            /* The stock boy must change their state so that a customer knows that they are ready to help in the customer's aisle */
                            /* SetStockBoysStatus(_stockBoyIndex, aisleID + NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS); */
                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " sets his status to #", aisleID+NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS, " and signals so customers waiting in this aisle realize he is willing to help.\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " customersWaiting[customersWaiting][", aisleID, "]->Signal()\n");
                            #endif

                            Signal(_customersWaitingInAisleToAskQuestionCV[aisleID], customersWaiting);
                            _customersWaitingInAisleToAskQuestionMV[aisleID]--;
                            /* Now the customer can ask his/her question. */
                            /* Lets wait to receive the Item Number */

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Acquire()\n");
                            #endif

                            Acquire(questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customersWaiting->Release()\n");
                            #endif

                            Release(customersWaiting);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customersWaiting->Release() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Wait()\n");
                            #endif

                            Wait(_customerItemQuestionCV[stockBoyId], questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Wait()\n Done!");
                            #endif

                            itemIDQuestioned = _customerItemQuestionMV[stockBoyId];
                            customerIDasking = _customerID_AskingQuestionMV[stockBoyId];

                            #ifdef PRINT_OUTPUT_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, "] is approached by Customer [", customerIDasking, "] for assistance.\n");
                            #endif
                            /* Lets answer the question asked */
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " Answer[", stockBoyId, "]->Acquire()\n");
                            #endif

                            Acquire(answerLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " Answer[", stockBoyId, "]->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Release()\n");
                            #endif

                            Release(questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Release() Done\n");
                            #endif

                            /* aisleIDAns = GetAisleNumber(theStoreInHomeDepot, itemIDQuestioned); */
                            {
                                aisleIDAns = itemsInStore[itemIDQuestioned]._aisle;
                            }

                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_7("StockBoy [", stockBoyId, " the aisle ID for item#", itemIDQuestioned, " is #", aisleIDAns, "\n");
                            #endif

                            _stockBoyAisleAnswerMV[stockBoyId] = aisleIDAns;

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answerCV[", stockBoyId, "][answerLock]->Signal()\n");
                            #endif

                            Signal(_stockBoyAisleAnswerCV[stockBoyId], answerLock);

                            #ifdef PRINT_OUTPUT_STOCKBOY
                                printf_9("StockBoy [", stockBoyId, "] gave aisle [", aisleIDAns, "] to Customer [", customerIDasking, "] for item [", itemIDQuestioned, "]\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customerWaiting->Acquire()\n");
                            #endif

                            Acquire(customersWaiting);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customerWaiting->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answer[", stockBoyId, "]->Release()\n");
                            #endif

                            Release(answerLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answer[", stockBoyId, "]->Release Done!()\n");
                            #endif
                        }
                        _stockBoyIdInAisleToAnswerQuestionMV[aisleID] = NOT_FOUND;
                    }

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customerWaiting->Release()\n");
                    #endif

                    Release(customersWaiting);

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customerWaiting->Release() Done!\n");
                    #endif
                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " stockBoyStatus->Acquire()\n");
                    #endif

                    /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                    Acquire(_stockBoysStatusLock);
                    _stockBoysStatus[stockBoyId] = -1;
                    Release(_stockBoysStatusLock);
                }

                #ifdef PRINT_EXTRA_LOG_STOCKBOY
                    printf_3("StockBoy #", stockBoyId, " is back from service\n");
                #endif

                justWokeup = FALSE;
            } else {
                /* before we go on break, lets see if any customer has any question waiting in service area. */
                /* AnswerQuestionsOfCustomers(stockboy, SERVICE_AREA_LINE); */
                {
                    aisleID = currentAisleIndex;
                    customersWaiting = _customersWaitingInAisleToAskQuestionLock[aisleID];
                    questionLock = _customerItemQuestionLock[stockBoyId];
                    answerLock = _stockBoyAisleAnswerLock[stockBoyId];
                    stockBoysStatus = _stockBoysStatusLock;

                    /* Check for customers needing help. - Customers will find StockBoys at any aisle, at any time. */
                    /*                                   - the Customer has no way of knowing when the stock boy will be ready to help them which */
                    /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                    Acquire(_stockBoysStatusLock);
                    _stockBoysStatus[stockBoyId] = -1;
                    Release(_stockBoysStatusLock);

                    #ifdef PRINT_EXTRA_LOG_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " lets see if any body has any questions\n");
                    #endif
                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customersWaiting->Acquire()\n");
                    #endif

                    Acquire(customersWaiting);

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customersWaiting->Acquire() Done!\n");
                    #endif

                    if(_stockBoyIdInAisleToAnswerQuestionMV[aisleID] == NOT_FOUND &&
                       _customersWaitingInAisleToAskQuestionMV[aisleID] > 0) {

                        _stockBoyIdInAisleToAnswerQuestionMV[aisleID] = stockBoyId;
                        while (_customersWaitingInAisleToAskQuestionMV[aisleID] > 0 ){
                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_7("StockBoy [", stockBoyId, " finds out there are ", _customersWaitingInAisleToAskQuestionMV[aisleID], " customers waiting to ask question in Aisle#", aisleID, "lock.\n");
                            #endif
                            /* There is a customer needing help */
                            /* The stock boy must change their state so that a customer knows that they are ready to help in the customer's aisle */
                            /* SetStockBoysStatus(_stockBoyIndex, aisleID + NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS); */
                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " sets his status to #", aisleID+NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS, " and signals so customers waiting in this aisle realize he is willing to help.\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " customersWaiting[customersWaiting][", aisleID, "]->Signal()\n");
                            #endif

                            Signal(_customersWaitingInAisleToAskQuestionCV[aisleID], customersWaiting);
                            _customersWaitingInAisleToAskQuestionMV[aisleID]--;
                            /* Now the customer can ask his/her question. */
                            /* Lets wait to receive the Item Number */

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Acquire()\n");
                            #endif

                            Acquire(questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customersWaiting->Release()\n");
                            #endif

                            Release(customersWaiting);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customersWaiting->Release() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Wait()\n");
                            #endif

                            Wait(_customerItemQuestionCV[stockBoyId], questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Wait()\n Done!");
                            #endif

                            itemIDQuestioned = _customerItemQuestionMV[stockBoyId];
                            customerIDasking = _customerID_AskingQuestionMV[stockBoyId];

                            #ifdef PRINT_OUTPUT_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, "] is approached by Customer [", customerIDasking, "] for assistance.\n");
                            #endif
                            /* Lets answer the question asked */
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " Answer[", stockBoyId, "]->Acquire()\n");
                            #endif

                            Acquire(answerLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " Answer[", stockBoyId, "]->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Release()\n");
                            #endif

                            Release(questionLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " question[", stockBoyId, "]->Release() Done\n");
                            #endif

                            /* aisleIDAns = GetAisleNumber(theStoreInHomeDepot, itemIDQuestioned); */
                            {
                                aisleIDAns = itemsInStore[itemIDQuestioned]._aisle;
                            }

                            #ifdef PRINT_EXTRA_LOG_STOCKBOY
                                printf_7("StockBoy [", stockBoyId, " the aisle ID for item#", itemIDQuestioned, " is #", aisleIDAns, "\n");
                            #endif

                            _stockBoyAisleAnswerMV[stockBoyId] = aisleIDAns;

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answerCV[", stockBoyId, "][answerLock]->Signal()\n");
                            #endif

                            Signal(_stockBoyAisleAnswerCV[stockBoyId], answerLock);

                            #ifdef PRINT_OUTPUT_STOCKBOY
                                printf_9("StockBoy [", stockBoyId, "] gave aisle [", aisleIDAns, "] to Customer [", customerIDasking, "] for item [", itemIDQuestioned, "]\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customerWaiting->Acquire()\n");
                            #endif

                            Acquire(customersWaiting);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_3("StockBoy [", stockBoyId, " customerWaiting->Acquire() Done!\n");
                            #endif
                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answer[", stockBoyId, "]->Release()\n");
                            #endif

                            Release(answerLock);

                            #ifdef PRINT_LOCKS_STOCKBOY
                                printf_5("StockBoy [", stockBoyId, " answer[", stockBoyId, "]->Release Done!()\n");
                            #endif
                        }
                        _stockBoyIdInAisleToAnswerQuestionMV[aisleID] = NOT_FOUND;
                    }

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customerWaiting->Release()\n");
                    #endif

                    Release(customersWaiting);

                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " customerWaiting->Release() Done!\n");
                    #endif
                    #ifdef PRINT_LOCKS_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, " stockBoyStatus->Acquire()\n");
                    #endif

                    /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                    Acquire(_stockBoysStatusLock);
                    _stockBoysStatus[stockBoyId] = -1;
                    Release(_stockBoysStatusLock);
                }

                /* GoToBreak(stockboy); */
                {
                    /* We are currently unavailable */
                    /* SetStockBoysStatus(stockboy, stockBoyId, -1); */
                    Acquire(_stockBoysStatusLock);
                    _stockBoysStatus[stockBoyId] = -1;
                    Release(_stockBoysStatusLock);

                    stockBoysBreakLock = _stockBoyBreakLock;
                    Acquire(stockBoysBreakLock);
                    _stockBoyOnBreakMV++;

                    #ifdef PRINT_OUTPUT_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, "] is going on break.\n");
                    #endif

                    Wait(_stockBoysOnBreakCV, stockBoysBreakLock);

                    #ifdef PRINT_OUTPUT_STOCKBOY
                        printf_3("StockBoy [", stockBoyId, "] got call from Manager.\n");
                    #endif

                    Release(stockBoysBreakLock);
                }

                justWokeup = TRUE;
            }
        }
    }
    Exit(0);
}


int _customerCounterLock;
int customerCounter;
int customerID;
int _customerID;
int randomVar;
int _wantsToReturnItems;
Aisle* aisleToSearch;
int clerkLock;
int customerLock;
int clerkLineLock;
int itemLock;
int reStockLock;
int customersWaiting;
int customersWaitingCondition;
int questionLock;
int answerLock;
int questionCondition;
int answerCondition;
int waitForClerksToReturn;
int total;
int shoppingListIndex;
int currentItemIDToPassToClerk;
int shortestLineLength;
int shortestLineIndex;
int anyClerkOnBreak;
int clerksOnBreak;
int couldPickupItem;
int currentStockBoyIndex;
int currentStockBoyStatus;
int aisleThatWeFoundTheStockBoyIn;
int aisleNumber;
int currentAisleIndex;
int chanceToFindTheAisle;
int currentStockBoyIndex;
int shoppingListIndex;
int currentItemIDToPickup;
int clerkID;
int itemId;
int _shoppingList[MAX_SHOPPING_LIST];
int _shoppingListSize;

void CustomerThread() {
    randomVar = Rand(5);
    _wantsToReturnItems = (randomVar == 5);

    Acquire(_customerCounterLock);
    customerID = customerCounter;
    customerCounter++;
    Release(_customerCounterLock);

    /* DoShopping(customerID, wantsToReturnItems); */
    {
        _customerID = customerID;
        Acquire(_occupancyLock);
        _customersInStore ++;
        Release(_occupancyLock);

        for(i = 0; i < MAX_SHOPPING_LIST; i++) {
            _shoppingList[i] = Rand(MAX_ITEMS) - 1;
        }
        _shoppingListSize = MAX_SHOPPING_LIST;
        if (_wantsToReturnItems == FALSE) {
            #ifdef PRINT_OUTPUT_CUSTOMER
                printf_5("Customer [", customerID, "] wants to buy [", _shoppingListSize, "] no.of items.\n");
            #endif
        } else {
            #ifdef PRINT_OUTPUT_CUSTOMER
                printf_5("Customer [", customerID, "] needs to return [", _shoppingListSize, "] no.of items.\n");
            #endif
        }

        /* customer = &instance; */

        if (_wantsToReturnItems == FALSE) {
            /* We just got into the store, lets collect our items */

            /* CollectShoppingListItems(customer); */
            {
                for (shoppingListIndex = 0; shoppingListIndex < _shoppingListSize; shoppingListIndex++) {
                    currentItemIDToPickup = _shoppingList[shoppingListIndex];

                    #ifdef PRINT_EXTRA_LOG_CUSTOMER
                        printf_7("CUSTOMER# ", _customerID, ": Collecting item index# ", shoppingListIndex, " Num# ", currentItemIDToPickup, " \n");
                    #endif

                    /* aisleNumber = LookForAisleNumber(customer, currentItemIDToPickup); */
                    {
                        itemId = currentItemIDToPickup;

                        #ifdef IGNORE_STOCKBOYS
                            /* return GetAisleNumber(theStoreInHomeDepot, itemId); */
                            return itemsInStore[itemId]._aisle
                        #endif

                        aisleNumber = NOT_FOUND;

                        /* lets find out if we are lucky enough to know where the item is */
                        chanceToFindTheAisle = Rand(100);

                        /* 75% of times correctly can find the aisle number */
                        if (chanceToFindTheAisle <= 75) {
                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                printf_3("CUSTOMER# ", _customerID, ": Can find the aisle ourself \n");
                            #endif

                            /* aisleNumber = GetAisleNumber(theStoreInHomeDepot, itemId); */
                            {
                                aisleNumber = itemsInStore[itemId]._aisle;
                            }
                            printf_3("Got Aisle Number ", aisleNumber, "\n");
                        } else {
                            #ifdef PRINT_OUTPUT_CUSTOMER
                                printf_5("CUSTOMER# ", _customerID, "] is not able to find item [", itemId, "] and is searching for StockBoy.\n");
                            #endif

                            /* 25% of times he/she does not know the aisleNumber. */
                            /* lets look in aisles to find a stock boy and ask him the aisle number. */
                            /* first we need to lock statuses of stockBoys */
                            Acquire(_stockBoysStatusLock);
                            aisleThatWeFoundTheStockBoyIn = NOT_FOUND;

                            /* we have to go through aisles one by one to find a stock boy */
                            for(currentAisleIndex=0; currentAisleIndex < MAX_AISLES; currentAisleIndex++) {
                                /* Lets see if any stock boy is in current aisle */
                                for(currentStockBoyIndex=0; currentStockBoyIndex < MAX_STOCKBOYS; currentStockBoyIndex++) {
                                    currentStockBoyStatus = _stockBoysStatus[currentStockBoyIndex];
                                    if (currentStockBoyStatus == currentAisleIndex) {
                                        aisleThatWeFoundTheStockBoyIn = currentAisleIndex;
                                        break;
                                    }
                                }
                                if (aisleThatWeFoundTheStockBoyIn != NOT_FOUND) {
                                    break;
                                }
                            }

                            if (aisleThatWeFoundTheStockBoyIn == NOT_FOUND) {
                                /* Couldn't find any stock boys in any aisle, so we should form a line */
                                /* in service area */
                                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                    printf_5("CUSTOMER# ", _customerID, ": LookForAisleNumber(itemID# ", itemId, ") Couldn't find any stock boy in aisles! SERVICE BUTTUN RINGED and wait for stock boy!\n");
                                #endif
                                #ifdef PRINT_OUTPUT_CUSTOMER
                                    printf_3("CUSTOMER# ", _customerID, "] looked in all aisle for StockBoy. He is now requesting help by pressing service button.\n");
                                #endif

                                aisleThatWeFoundTheStockBoyIn = SERVICE_AREA_LINE; /* SERVICE_AREA_LINE = MAX_AISLES = last index of the array */
                            }
                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                else {
                                    printf_5("CUSTOMER# ", _customerID, ": Waiting for a stock boy in aisle# ", aisleThatWeFoundTheStockBoyIn, " \n");
                                }
                            #endif

                            customersWaiting = _customersWaitingInAisleToAskQuestionLock[aisleThatWeFoundTheStockBoyIn];
                            customersWaitingCondition = _customersWaitingInAisleToAskQuestionCV[aisleThatWeFoundTheStockBoyIn];

                            Release(_stockBoysStatusLock);
                            Acquire(customersWaiting);

                            /* Please notice that the following function returns a pointer so we can easily increment its content */
                            _customersWaitingInAisleToAskQuestionMV[aisleThatWeFoundTheStockBoyIn]++;

                            /* Lets wait for stock boy to finish his task. */
                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                printf_5("CUSTOMER# ", _customerID, ": LookForAisleNumber(itemID# ", itemId, ") Waiting for a stock boy to help us\n");
                            #endif

                            Wait(customersWaitingCondition, customersWaiting);

                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                printf_5("CUSTOMER# ", _customerID, ": LookForAisleNumber(itemID# ", itemId, ") just got woken up by a stock boy\n");
                            #endif

                            /* a stock boy just woke us up to answer our question. We need to search for that stock boy. */
                            /* as convention, once a stock boy wakes a customer up, he needs to add MAX_AISLES to his */
                            /* status so the customer can find him. i.e. now we need to search for a stock boy */
                            /* with his status set to (aisleThatWeFoundTheStockBoyIn+NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS) */

                            currentStockBoyIndex  = _stockBoyIdInAisleToAnswerQuestionMV[aisleThatWeFoundTheStockBoyIn];
                            /* ASSERT (currentStockBoyIndex < MAX_STOCKBOYS); / * We assume we must find a stockboy ready for help * / */

                            questionLock = _customerItemQuestionLock[currentStockBoyIndex];
                            answerLock = _stockBoyAisleAnswerLock[currentStockBoyIndex];
                            questionCondition = _customerItemQuestionCV[currentStockBoyIndex];
                            answerCondition = _stockBoyAisleAnswerCV[currentStockBoyIndex];

                            #ifdef PRINT_OUTPUT_CUSTOMER
                                printf_5("CUSTOMER# ", _customerID, "] is asking for assistance from StockBoy [", currentStockBoyIndex, "]\n");
                            #endif

                            Release(customersWaiting);
                            Acquire(questionLock);

                            /* currentStockBoyIndex is who we can ask our question from. */
                            /* we need to ask our question through locking a shared monitor variable. */
                            /* This needs to happen before we release the customersWaitingInAisleToAskQuestionLock, because */
                            /* we need to make other customers wait till our question is being answered. */
                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                printf_5("CUSTOMER# ", _customerID, " locked the question for Stockboy ", currentStockBoyIndex, "\n");
                            #endif

                            _customerItemQuestionMV[currentStockBoyIndex] = itemId;
                            _customerID_AskingQuestionMV[currentStockBoyIndex] = _customerID;
                            Signal(questionCondition, questionLock);

                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                printf_7("CUSTOMER# ", _customerID, " put the item#", itemId, " in the question place for Stockboy ", currentStockBoyIndex, "\n");
                            #endif

                            /* We asked our question, now we need to wait till stock boy receives the answer, and hands over the aisle number */
                            Acquire(answerLock);

                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                printf_5("CUSTOMER# ", _customerID, " acquired the answer lock for Stockboy ", currentStockBoyIndex, "\n");
                            #endif

                            Release(questionLock);

                            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                printf_5("CUSTOMER# ", _customerID, " waiting for answer from Stockboy ", currentStockBoyIndex, "\n");
                            #endif

                            Wait(answerCondition, answerLock);

                            /* Stock boy just provided the aisle number, lets grab it */
                            aisleNumber = _stockBoyAisleAnswerMV[currentStockBoyIndex];

                            #ifdef PRINT_OUTPUT_CUSTOMER
                                printf_7("CUSTOMER# ", _customerID, "] got aisle [", aisleNumber, "] from StockBoy [", currentStockBoyIndex, "\n");
                            #endif

                            Release(answerLock);
                        }

                        #ifdef PRINT_EXTRA_LOG_CUSTOMER
                            printf_7("CUSTOMER# ", _customerID, ": LookForAisleNumber(itemID# ", itemId, ") the aisle# is ", aisleNumber, "\n");
                        #endif

                        aisleNumber = (aisleNumber);
                    }

                    /* by now we know what is our aisleNumber */
                    /* go to the aisle (this can be simply a tele-port to that aisle) */
                    /* ASSERT (aisleNumber >=0 && aisleNumber < MAX_AISLES); */
                    /* aisleToSearch = theStoreInHomeDepot->aisles[aisleNumber]; */

                    #ifndef IGNORE_STOCKBOYS
                        couldPickupItem = FALSE;
                        while (couldPickupItem == FALSE) {
                            /* couldPickupItem = PickupItem(customer, aisleNumber, currentItemIDToPickup); */
                            {
                                #ifdef IGNORE_STOCKBOYS
                                    return(TRUE);
                                #endif

                                itemLock = _shelfLock[itemId];
                                reStockLock = _customerWaitingForReStockLock;

                                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                    printf_7("CUSTOMER# ", _customerID, ": PickupItem(aisle# ", aisleNumber, ", itemID# ", itemId, ") Started!\n");
                                #endif
                                #ifdef PRINT_LOCKS_STOCKBOY
                                    printf_5("CUSTOMER# ", _customerID, " itemLock[", itemId, "]->Acquire()!\n");
                                #endif

                                Acquire(itemLock);

                                #ifdef PRINT_LOCKS_STOCKBOY
                                    printf_5("CUSTOMER# ", _customerID, " itemLock[", itemId, "]->Acquire() Done!\n");
                                #endif
                                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                    printf_7("CUSTOMER# ", _customerID, ": PickupItem(aisle# ", aisleNumber, ", itemID# ", itemId, ") Locked the item\n");
                                #endif

                                couldPickupItem = FALSE;

                                do {
                                    /* couldPickupItem = PickupItemFromStore(theStoreInHomeDepot, itemId); */
                                    {
                                        if (itemsInStore[itemId]._quantity > 0) {
                                            itemsInStore[itemId]._quantity--;
                                            couldPickupItem = TRUE;

                                        } else {

                                            couldPickupItem = FALSE;
                                        }
                                    }

                                    if (couldPickupItem == FALSE) {
                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_5("CUSTOMER# ", _customerID, " itemLock[", itemId, "]->Release()!\n");
                                        #endif

                                        Release(itemLock);

                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_5("CUSTOMER# ", _customerID, " itemLock[", itemId, "]->Release() Done!\n");
                                        #endif
                                        #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                            printf_7("CUSTOMER# ", _customerID, ": PickupItem(aisle# ", aisleNumber, ", itemID# ", itemId, ") Couldn't pickup item. Lets wait for a stock boy to re stock it.!\n");
                                        #endif
                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_3("CUSTOMER# ", _customerID, " reStockLock->Acquire()!\n");
                                        #endif

                                        Acquire(reStockLock);

                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_3("CUSTOMER# ", _customerID, " reStockLock->Acquire() Done!\n");
                                        #endif
                                        #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                            printf_7("CUSTOMER# ", _customerID, ": PickupItem(aisle# ", aisleNumber, ", itemID# ", itemId, ") lets get into the line of customers waiting for re stocking.!\n");
                                        #endif

                                        _customersWaitingForRestock[itemId]++;

                                        /* lets wait for a stock boy to re stock this item */
                                        #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                            printf_7("CUSTOMER# ", _customerID, ": PickupItem(aisle# ", aisleNumber, ", itemID# ", itemId, ") lets wait on this line!\n");
                                        #endif
                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_5("CUSTOMER #", _customerID, " itemCV[reStockLock][", itemId, "]->Wait()!\n");
                                        #endif

                                        Wait(_itemWaitCV[itemId], reStockLock);

                                        /* We just got a signal from stock boy that item is available for pickup */
                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_5("CUSTOMER #", _customerID, " itemCV[reStockLock][", itemId, "]->Wait() Done!\n");
                                        #endif
                                        #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                            printf_7("CUSTOMER# ", _customerID, ": PickupItem(aisle# ", aisleNumber, ", itemID# ", itemId, ") just got the signal from stock boy that item is available.\n");
                                        #endif
                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_5("CUSTOMER #", _customerID, " itemLock[", itemId, "]->Acquire()!\n");
                                        #endif

                                        Acquire(itemLock);

                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_5("CUSTOMER #", _customerID, " itemLock[", itemId, "]->Acquire() Done!\n");
                                        #endif
                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_3("CUSTOMER #", _customerID, " restockLock->Release()!\n");
                                        #endif

                                        Release(reStockLock);

                                        #ifdef PRINT_LOCKS_STOCKBOY
                                            printf_3("CUSTOMER #", _customerID, " reStockLock->Release() Done!\n");
                                        #endif
                                    }
                                } while(couldPickupItem == FALSE);

                                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                                    printf_7("CUSTOMER# ", _customerID, ": PickupItem(aisle# ", aisleNumber, ", itemID# ", itemId, ") Successfully picked up the item!\n");
                                #endif
                                #ifdef PRINT_LOCKS_STOCKBOY
                                    printf_5("CUSTOMER# ", _customerID, " itemLock[", itemId, "]->Release()!\n");
                                #endif

                                Release(itemLock);

                                #ifdef PRINT_LOCKS_STOCKBOY
                                    printf_5("CUSTOMER# ", _customerID, " itemLock[", itemId, "]->Release() Done!\n");
                                #endif

                                couldPickupItem = (couldPickupItem);
                            }
                        }
                    #endif
                }
            }

            /* Now all of the items have been collected. lets check out */
        }

        #ifndef IGNORE_CLERKS
            /* we need to get into the shortest line */
            /* and wait till its our turn. */

            /* clerkID = GetIntoTheShortestClerkLine(customer); */
            {
                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                    printf_3("CUSTOMER# ", _customerID, ": GetIntoTheShortestClerkLine() lets find the shortest line\n");
                #endif

                clerkLineLock = _clerkLinelock;
                waitForClerksToReturn = _customerNeedsClerkAssitanceLock;

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Acquire()\n");
                #endif

                Acquire(clerkLineLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Acquire() Done!\n");
                #endif

                /* shortestLineIndex = LookForShortestClerkLine(customer); */
                {
                    /* The locking is happening outside of this function */
                    shortestLineLength = MAX_INT;
                    shortestLineIndex = NOT_FOUND;

                    /* find the shortest line */
                    anyClerkOnBreak = FALSE;
                    clerksOnBreak = 0;
                    for(i = 0; i< MAX_CLERKS; i++) {
                        if (_clerkStatus[i] == CLERK_BREAK) {
                            clerksOnBreak++;
                            anyClerkOnBreak = TRUE;
                        } else if (_clerkLineLength[i] < shortestLineLength) {
                            /* then clerk isn't on break */
                            shortestLineLength = _clerkLineLength[i];
                            shortestLineIndex = i;
                        }
                    }
                    if (shortestLineLength > 5 && anyClerkOnBreak == TRUE) {
                        /* lets not jump into this line but lets wait for a new clerk to come */
                        shortestLineIndex = NOT_FOUND;
                    }

                    #ifdef PRINT_EXTRA_LOG_CUSTOMER
                        if (shortestLineIndex != NOT_FOUND) {
                            printf_9("CUSTOMER# ", _customerID, ": LookForShortestClerkLine() the shortest line is ", shortestLineIndex, " with ", shortestLineLength, " customers in it, while there are ", clerksOnBreak, " clerks on break.\n");
                        }
                    #endif

                    shortestLineIndex = (shortestLineIndex);
                }

                /* We need to notify the manager if all of the clerks are on break. */
                if (shortestLineIndex == NOT_FOUND)  {
                    while (shortestLineIndex == NOT_FOUND) {

                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Release()\n");
                        #endif

                        Release(clerkLineLock);

                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Release() Done!\n");
                        #endif
                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " waitForClerkToReturn->Acquire()\n");
                        #endif

                        Acquire(waitForClerksToReturn);

                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " waitForClerkToReturn->Acquire() Done!\n");
                        #endif
                        #ifdef PRINT_EXTRA_LOG_CUSTOMER
                            printf_3("CUSTOMER# ", _customerID, ": GetIntoTheShortestClerkLine() all of the clerks are in break, ask manager to send one for us\n");
                        #endif

                        (_customersNeedingAsistanceMV)++;
                        /* Wait for manager so he can tell a clerk to come back to work. */
                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " customerAssistance[clerkLineLock]->Wait()\n");
                        #endif

                        Wait(_customerNeedsClerkAssitanceCV, waitForClerksToReturn);

                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " customerAssistance[clerkLineLock]->Wait() Done!\n");
                        #endif
                        #ifdef PRINT_EXTRA_LOG_CUSTOMER
                            printf_3("CUSTOMER# ", _customerID, ": GetIntoTheShortestClerkLine() Just got woken up to get into line\n");
                        #endif

                        /* Now we can check again for shortest line */
                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Acquire()\n");
                        #endif

                        Acquire(clerkLineLock);

                        #ifdef PRINT_LOCKS_CLERK
                            printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Acquire() Done!\n");
                        #endif

                        shortestLineIndex = _clerkIDSignalingToCustomer;
                    }

                    (_clerkLineLength[shortestLineIndex])++;

                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("CUSTOMER# ", _customerID, " customerShouldFindClerkCV->Signal()\n");
                    #endif

                    Signal(_customerShouldFindTheClerkCV, waitForClerksToReturn);

                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("CUSTOMER# ", _customerID, "waitForClerksToReturn->Release()\n");
                    #endif

                    Release(waitForClerksToReturn);

                    #ifdef PRINT_LOCKS_CLERK
                        printf_3("CUSTOMER# ", _customerID, "waitForClerksToReturn->Release() Done!\n");
                    #endif

                } else {
                    #ifdef PRINT_OUTPUT_CUSTOMER
                        printf_7("Customer [", _customerID, "] chose Clerk[", shortestLineIndex, "] with line length of [", _clerkLineLength[shortestLineIndex], "]\n");
                    #endif

                    /* by now we have found the shortest line. lets stay on the line */
                    (_clerkLineLength[shortestLineIndex])++;
                }
                #ifdef PRINT_LOCKS_CLERK
                    printf_5("CUSTOMER# ", _customerID, " clerkLineCV[", shortestLineIndex, "][clerkLineLock]->Wait()\n");
                #endif

                Wait(_clerkLineCV[shortestLineIndex], clerkLineLock);

                #ifdef PRINT_LOCKS_CLERK
                    printf_5("CUSTOMER# ", _customerID, " clerkLineCV[", shortestLineIndex, "][clerkLineLock]->Wait() Done!\n");
                #endif

                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                    printf_5("CUSTOMER# ", _customerID, ": GetIntoTheShortestClerkLine() Finally! its my turn in line#", shortestLineIndex, "\n");
                #endif

                /* At this point, we just woke up (its our turn) so */
                /* lets get out of the line and lock the clerk so no one else can interrupt us */
                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Release()\n");
                #endif

                Release(clerkLineLock);      /* We can safely release this lock, because clerk will not */
                                             /* signal other customers till he is done with current customer */
                #ifdef PRINT_LOCKS_CLERK
                    printf_3("CUSTOMER# ", _customerID, " clerkLineLock->Release() Done\n");
                #endif

                #ifdef PRINT_LOCKS_CLERK
                    printf_5("CUSTOMER# ", _customerID, " clerkLock[", shortestLineIndex, "]->Acquire()\n");
                #endif

                Acquire(_clerkLock[shortestLineIndex]);

                #ifdef PRINT_LOCKS_CLERK
                    printf_5("CUSTOMER# ", _customerID, " clerkLock[", shortestLineIndex, "]->Acquire() Done!\n");
                #endif

                clerkID = (shortestLineIndex);
            }

            /* Now its our turn. Lets provide our items to clerk */

            /* ProvideTheItemsToClerk(customer, clerkID); */
            {
                clerkLock = _clerkLock[clerkID];
                customerLock = _customerLock[clerkID];

                /*clerkLock has already been acquired. Clerk is in sleep and waiting for us to provide */
                /* the nature of transaction, customer ID, etc and then */
                /* provide our items one by one. */
                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                    printf_5("CUSTOMER# ", _customerID, ": ProvideTheItemsToClerk(clerk#", clerkID, ") started providing the items\n");
                #endif

                Acquire(_customerActionLock);
                _customerBeingHelped[clerkID] = _customerID;
                _customerWantsToScanItems[clerkID] = _wantsToReturnItems;
                Release(_customerActionLock);

                /* put the items in shared area and signal the clerk, wait for clerk's signal */
                /* so we can put the next item */
                for (shoppingListIndex = 0; shoppingListIndex < _shoppingListSize; shoppingListIndex++) {
                    currentItemIDToPassToClerk = _shoppingList[shoppingListIndex];
                    _nextItem[clerkID] = _shoppingList[shoppingListIndex];

                    #ifdef PRINT_OUTPUT_CUSTOMER
                        printf_7("Customer [", _customerID, "] gives item [", _shoppingList[shoppingListIndex], "] to Clerk[", clerkID, "]\n");
                    #endif

                    Signal(_clerkCV[clerkID], clerkLock);
                    Wait(_customerCV[clerkID], clerkLock);

                    #ifdef PRINT_EXTRA_LOG_CUSTOMER
                        printf_5("CUSTOMER# ", _customerID, ": ProvideTheItemsToClerk(clerk#", clerkID, ") Clerk said he is ready to take the next item\n");
                    #endif
                }

                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                    printf_5("CUSTOMER# ", _customerID, ": ProvideTheItemsToClerk(clerk#", clerkID, ") Let the clerk know we are done passing items\n");
                #endif
                #ifdef PRINT_OUTPUT_CUSTOMER
                    printf_7("Customer [", _customerID, "] tell Clerk [", clerkID, "], I have given you all my [", _shoppingListSize, "] items.\n");
                #endif

                _nextItem[clerkID] = NOT_FOUND; /* No more items to scan */
                Signal(_clerkCV[clerkID], clerkLock);
                Wait(_customerCV[clerkID], clerkLock);
            }

            /* Clerk lock is already acquired in previous step */
            /* so we are guaranteed we have the attention of clerk */
            /* lets pay the amount due or take our refund */

            /* TransferPayment(customer, clerkID); */
            {
                /* create local references to shared Locks/CV/MV */
                clerkLock = _clerkLock[clerkID];

                total = _moneyToTransfer[clerkID];

                #ifdef PRINT_OUTPUT_CUSTOMER
                    if (_wantsToReturnItems) {
                        printf_7("Customer [", _customerID, "] receives [", total, "] from Clerk ", clerkID, "and is now waiting for receipt.\n");
                    } else {
                        printf_7("Customer [", _customerID, "] pays [", total, "] to Clerk ", clerkID, "and is now waiting for receipt.\n");
                    }
                #endif

                Signal(_clerkCV[clerkID], clerkLock);

                /* Wait till clerk gives the receipt */
                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                    printf_5("CUSTOMER# ", _customerID, (_wantsToReturnItems)? ", Returning: TransferPayment(clerk#": ", Purchasing: TransferPayment(clerk#", clerkID, ") Wait for receipt.\n");
                #endif

                Wait(_customerCV[clerkID], clerkLock);

                #ifdef PRINT_OUTPUT_CUSTOMER
                    printf_5("Customer [", _customerID, "] got receipt from Clerk ", clerkID, " and is now leaving.\n");
                #endif

                /* Let the clerk know we pickup our receipt */
                Signal(_clerkCV[clerkID], clerkLock);

                #ifdef PRINT_EXTRA_LOG_CUSTOMER
                    printf_5("CUSTOMER# ", _customerID, (_wantsToReturnItems)? ", Returning: TransferPayment(clerk#": ", Purchasing: TransferPayment(clerk#", clerkID, ") Let the clerk know we got the receipt.\n");
                #endif

                Release(clerkLock);
            }

            #ifdef PRINT_LOCKS_CLERK
                printf_5("CUSTOMER #", _customerID, " clerkLock[", clerkID, "]->Release()\n");
            #endif

            Release(_clerkLock[clerkID]);

            #ifdef PRINT_LOCKS_CLERK
                printf_5("CUSTOMER #", _customerID, " clerkLock[", clerkID, "]->Release() Done!\n");
            #endif

        #endif

        /* LeaveStore(customer); */
        {
            #ifdef PRINT_EXTRA_LOG_CUSTOMER
                printf_3("CUSTOMER #", _customerID, (_wantsToReturnItems)? ", Returning: Leaving the store.\n": ", Purchasing: Leaving the store.\n");
            #endif

            Acquire(_occupancyLock);
            _customersInStore --;
            Release(_occupancyLock);
        }
    }
    Exit(0);
}

int doWork;
int collectAllTills;
/* int registerId; */
int registerStatusLock;
int registerLock;
int registerStatusCV;
int currentRegister;
int shouldIgnoreCurrentCashRegiter;
int tillAmount;
int clerksOnBreak;
int clerkLineLock;
int waitForClerksToReturn;
int anyItemNeedsToBeRestocked;
int reStockLock;
int cnt;
int customersWaitingLock;
int customersInServiceArea;
int stockBoysBreakLock;
int m;

void ManagerThread() {
    /* ManagerDoWork(); */
    {
        doWork = TRUE;
        collectAllTills = FALSE;
        for (i = 0; i < 20; i++) {
            Yield();
        }

        while (doWork) {
            /* srand (time(NULL)); */
            int randomVar = 5;/*Rand(100);*/

            if (randomVar <= 20) {
                #ifdef PRINT_OUTPUT_MANAGER
                    printf_3("------- Total Sale of the store until now is $[",(totalStoreSales), "]-------\n");
                #endif
            }

            if (randomVar <= 20 || collectAllTills == TRUE) {
                #ifdef PRINT_EXTRA_LOG_MANAGER
                    printf("MANAGER# lets empty till\n");
                #endif

                for (registerId = 0; registerId < MAX_CLERKS; registerId++) {
                    registerStatusLock = _registerLock[registerId];
                    registerLock = _fromRegisterInteractionLock[registerId];
                    registerStatusCV = _registerCV[registerId];
                    currentRegister = registerId;

                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        #ifdef PRINT_EXTRA_LOG_MANAGER
                            printf_3("MANAGER#: Lets acquire the lock for Cash register", registerId, "\n");
                        #endif
                    #endif

                    shouldIgnoreCurrentCashRegiter = FALSE;

                    #ifdef PRINT_EXTRA_LOG_MANAGER
                        printf_3("MANAGER: is going to acquire the lock for register#", registerId, "\n");
                    #endif

                    Acquire(registerStatusLock);

                    #ifdef PRINT_EXTRA_LOG_MANAGER
                        printf_3("MANAGER: acquired the lock for register#", registerId, "\n");
                    #endif

                    if (_managerEmtpyingTill[currentRegister] == -2) { /* cash register not initialized yet */
                        shouldIgnoreCurrentCashRegiter = TRUE;
                    } else {
                        while (_managerEmtpyingTill[currentRegister] != -1) {  /* ||  _theLocks->_peopleWaitingForCashRegister[currentRegister] > 0) { */
                            if (collectAllTills == TRUE) {
                                (_peopleWaitingForCashRegister[currentRegister])++;

                                #ifdef PRINT_EXTRA_LOG_MANAGER
                                    printf_3("MANAGER: is going to wait for  register#", registerId, "\n");
                                #endif

                                Wait(_peopleWaitingForCashRegiterCV[currentRegister], registerStatusLock);

                                #ifdef PRINT_EXTRA_LOG_MANAGER
                                    printf_3("MANAGER: Just got woken up from cash register #", registerId, "\n");
                                #endif

                            } else {
                                /* cash register busy, lets continue to other cash registers */
                                shouldIgnoreCurrentCashRegiter = TRUE;
                                break;
                            }
                        }
                    }

                    if (shouldIgnoreCurrentCashRegiter) {
                        Release(registerStatusLock);
                        continue;
                    }

                    _managerEmtpyingTill[registerId] = 1;
                    Signal(_registerCV[registerId], registerStatusLock);

                    Acquire(registerLock);
                    Release(registerStatusLock);

                    /* Lets wait for cash register till to put its till in shared memory */
                    #ifdef PRINT_EXTRA_LOG_CASH_REGISTER
                        #ifdef PRINT_EXTRA_LOG_MANAGER
                            printf_3("MANAGER#: Lets wait for Cash register ", registerId, " to provide its till\n");
                        #endif
                    #endif

                    Wait(_fromRegisterInteractionCV[registerId], registerLock);
                    tillAmount = _moneyToTransfer[registerId];
                    /* IncreaseSales(manager, tillAmount); */
                    (totalStoreSales) += tillAmount;

                    /* Pickup the till balance */
                    #ifdef PRINT_OUTPUT_MANAGER
                        printf_3("Manager emptied Cash Register [", registerId, "] drawer.\n");
                        printf_3("Manager has total sale of $[", (totalStoreSales), "].\n");
                    #endif

                    Signal(_toRegisterInteractionCV[registerId], registerLock);
                    Release(registerLock);
                }
            }

            /* check the clerk lines to see if any Clerks signaled us for help */
            #ifdef PRINT_EXTRA_LOG_MANAGER
                printf("MANAGER: is going to acquire signalManagerClerkhelp \n");
            #endif

            Acquire(_signalManagerClerkHelp);

            #ifdef PRINT_EXTRA_LOG_MANAGER
                printf("MANAGER: acquired signalManagerClerkhelp \n");
            #endif

            for (i = 0; i < MAX_CLERKS; i++) {
                /* did a clerk signal us? */
                if (_storeNeedsMoreClerks[i] == TRUE) {
                    /* tell the observer */

                    #ifdef PRINT_OUTPUT_MANAGER
                        printf_3("Manager got a call from Clerk [", i, "]\n");
                    #endif
                    /* turn off the clerk's signal */
                    _storeNeedsMoreClerks[i] = FALSE;

                    /* get the lock for waking up a clerk */
                    Acquire(_clerksOnBreakLock);

                    /* check to see if there are any clerks to awaken */
                    clerksOnBreak = _clerksOnBreakMV;

                    if (clerksOnBreak > 0) {
                        #ifdef PRINT_OUTPUT_MANAGER
                            printf("Manager wakes up Clerk.\n");
                        #endif

                        /* decrement the counter */
                        _clerksOnBreakMV--;

                        /* signal the next Clerk to Wake up */
                        Signal(_clerksOnBreakCV, _clerksOnBreakLock);
                    }

                    /* release the lock for waking a clerk */
                    Release(_clerksOnBreakLock);
                    break;
                }
            }
            /* we're done looking at the signals from the clerk */
            Release(_signalManagerClerkHelp);

            /*
             * Lets see if customers need to work with clerks but all of the are in break
             */
            clerkLineLock = _clerkLinelock;
            waitForClerksToReturn = _customerNeedsClerkAssitanceLock;

            Acquire(waitForClerksToReturn);

            if (_customersNeedingAsistanceMV > 0) {
                #ifdef PRINT_EXTRA_LOG_MANAGER
                    printf_3("MANAGER: There are ", _customersNeedingAsistanceMV, " customers waiting for clerk\n");
                #endif

                /* get the lock for waking up a clerk */
                Acquire(_clerksOnBreakLock);

                /* check to see if there are any clerks to awaken */
                if (_clerksOnBreakMV > 0) {
                    #ifdef PRINT_OUTPUT_MANAGER
                        printf("Manager wakes up Clerk.\n");
                    #endif

                    /* decrement the counter */
                    _clerksOnBreakMV--;

                    /* signal the next Clerk to Wake up */
                    Signal(_clerksOnBreakCV, _clerksOnBreakLock);
                } else {
                    #ifdef PRINT_EXTRA_LOG_MANAGER
                        printf("MANAGER Cant wake up any Clerk since no one is in break.\n");
                    #endif
                }

                Release(_clerksOnBreakLock);
            }
            Release(waitForClerksToReturn);

            /*
             * Lets check on stockboys and see if we need call any to return from break
             * if any customer is waiting for an item to be restocked OR
             * any customer is waiting in service area go ahead and wake up a stockboy
             */
            anyItemNeedsToBeRestocked = FALSE;

            reStockLock = _customerWaitingForReStockLock;

            #ifdef PRINT_LOCKS_STOCKBOY
                /* printf("Manager reStockLock->Acquire()!\n"); */
            #endif

            Acquire(reStockLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                /* printf("Manager reStockLock->Acquire() Done!\n"); */
            #endif

            for (cnt = 0; cnt < MAX_ITEMS; cnt++) {
                if(_customersWaitingForRestock[cnt] > 0 &&
                   _stockBoyReStockingItem[cnt] == NOT_FOUND) {
                    anyItemNeedsToBeRestocked = TRUE;
                }
            }

            #ifdef PRINT_LOCKS_STOCKBOY
                /* printf("Manager reStockLock->Relase()!\n"); */
            #endif

            Release(reStockLock);

            #ifdef PRINT_LOCKS_STOCKBOY
                /* printf("Manager reStockLock->Release() Done!\n"); */
            #endif

            customersWaitingLock = _customersWaitingInAisleToAskQuestionLock[SERVICE_AREA_LINE];

            #ifdef PRINT_EXTRA_LOG_MANAGER
                printf("MANAGER: Going to acquired the customers waiting lock\n");
            #endif

            Acquire(customersWaitingLock);

            customersInServiceArea = _customersWaitingInAisleToAskQuestionMV[SERVICE_AREA_LINE];

            Release(customersWaitingLock);

            if (anyItemNeedsToBeRestocked || customersInServiceArea > 0) {
                /* Waking up a stock boy */
                stockBoysBreakLock = _stockBoyBreakLock;
                Acquire(stockBoysBreakLock);

                if (_stockBoyOnBreakMV > 0) {
                    Signal(_stockBoysOnBreakCV, stockBoysBreakLock);

                    #ifdef PRINT_OUTPUT_MANAGER
                        printf("Manager wakes up stock boy.\n");
                    #endif

                    _stockBoyOnBreakMV--;
                }

                Release(stockBoysBreakLock);
            }
            for (m = 0; m < 10; m++) {
                Yield();
            }



            Acquire(_occupancyLock);

            if (_customersInStore == 0) {
                Release(_occupancyLock);

                if (collectAllTills == TRUE) {

                    Acquire(_clerksOnBreakLock);
                    /* check to see if there are still working */

                    if (_clerksOnBreakMV == MAX_CLERKS) {
                        Release(_clerksOnBreakLock);
                        Acquire(_stockBoyBreakLock);

                        if (_stockBoyOnBreakMV == MAX_STOCKBOYS) {
                            Release(_stockBoyBreakLock);
                            /* Everyone is out, we can collect all of the tills now */
                            collectAllTills = TRUE;
                        } else {
                            Release(_stockBoyBreakLock);
                        }
                    } else {
                        Release(_clerksOnBreakLock);
                    }
                } else {

                    #ifdef PRINT_OUTPUT_MANAGER
                        printf("MANAGER: no one in the store, manager can close up.\n");
                    #endif

                    for (tmp = 0; tmp < MAX_CLERKS; tmp++) {
                        printf_5("Total Sale from Cash Register [", tmp, "] is $[", registerSales[tmp] ,"]\n");
                    }

                    printf_3("Total Sale of the entire store is $[", totalStoreSales, "]\n");
                    return;
                }
            } else {
                Release(_occupancyLock);
            }
        }
    }
    Exit(0);
}



int main() {
    printf("HomeDepot Simulation User Program\n");

    /* theLocksInHomeDepot = getLocksInstance(); */
    /* theStoreInHomeDepot = getStoreInstance(); */

    setupLocks();

    printf_3("Number of Clerks = [", MAX_CLERKS, "]\n");
    printf_3("Number of StockBoys = [", MAX_STOCKBOYS, "]\n");
    printf_3("Number of CashRegisters = [", MAX_CLERKS, "]\n");
    printf_3("Number of Customers = [", MAXIMUM_OCCUPANCY, "]\n");
    printf_3("Number of Managers = [", 1, "]\n");
    printf_3("Number of Aisle = [", MAX_AISLES, "]\n");
    printf("  Items:\n");
    printf("    Number - Price\n");

    for (i = 0; i < MAX_ITEMS; i++) {
        printf_5("    [", i, "] - $[", itemsInStore[i]._price, "]\n");
    }


    /*  Make Some Cash Registers */
    _cashRegisterLock = CreateLock("Cash Register Counter lock");
    _cashRegisterCounter = 0;
    for (i = 0; i < MAX_CLERKS; i++) {
        name = "Register";
        Fork(name, 8, CashRegisterThread);
    }


    /*  Make Some Clerks */
    _counterLock = CreateLock("Clerk counter Lock");
    _clerkCounter = 0;
    for (i = 0; i < MAX_CLERKS; i++) {
        name = "Clerk";
        Fork(name, 5, ClerkThread);
    }


    /* Make Some StockBoy */
    _stockBoyLock = CreateLock("StockBoy counter Lock");
    stockBoyCounter = 0;
    for (i = 0; i < MAX_STOCKBOYS; i++) {
        name = "StockBoy";
        Fork(name, 8, StockBoyThread);
    }


    /* Make Some Customers  */
    _customerCounterLock = CreateLock("Customer counter Lock");
    customerCounter = 0;
    for (i = 0; i < MAXIMUM_OCCUPANCY; i++) {
        name = "Customer";
        Fork(name, 8, CustomerThread);
    }


    /* Make a Manager */
    Yield();
    name = "Manager";
    Fork(name, 8, ManagerThread);


    /* Wait around for the store to close */
    do {
        Acquire(_occupancyLock);
        if (_customersInStore == 0) {
            Release(_occupancyLock);
            return;
        } else {
            Release(_occupancyLock);
        }
        Yield();
    } while (TRUE);

    Exit(0);
}
